#ifndef __RINGBUFFER_H__
#define __RINGBUFFER_H__


template<size_t _TbufferSize>
class RingBuffer
{
private:
	char _bytes[_TbufferSize];
	size_t _start;
	size_t _used;

public:
	inline RingBuffer()
	{
		_start = _used = 0;
		memset(_bytes, 0, _TbufferSize);
	}

	inline void Write(const void *bytes, size_t size)
	{
		size_t startLocation = _start + _used;
		if(startLocation >= _TbufferSize)
			memcpy(_bytes + startLocation - _TbufferSize, bytes, size);
		else
		{
			size_t endWritable = _TbufferSize - startLocation;
			if(endWritable >= size)
				memcpy(_bytes + startLocation, bytes, size);
			else
			{
				memcpy(_bytes + startLocation, bytes, endWritable);
				memcpy(_bytes, static_cast<const char *>(bytes) + endWritable, size - endWritable);
			}
		}

		_used += size;
	}

	inline size_t Peek(void *buf, size_t size) const
	{
		if(size > _used)
		{
			memset(static_cast<char *>(buf) + _used, 0, size - _used);
			size = _used;
		}

		size_t endAvailable = _TbufferSize - _start;

		if(endAvailable >= size)
			memcpy(buf, _bytes + _start, size);
		else
		{
			memcpy(buf, _bytes + _start, endAvailable);
			memcpy(static_cast<char *>(buf) + endAvailable, _bytes, size - endAvailable);
		}

		return size;
	}

	inline void Skip(size_t size)
	{
		if(size > _used)
			size = _used;
		_start += size;
		_used -= size;

		if(_start >= _TbufferSize)
			_start -= _TbufferSize;
	}

	inline size_t Read(void *buf, size_t size)
	{
		size_t amountRead = Peek(buf, size);
		Skip(size);

		return amountRead;
	}

	inline size_t BytesStored() const
	{
		return _used;
	}

	inline size_t BytesFree() const
	{
		return _TbufferSize - _used;
	}
};



#endif
